#ifdef IMAM_LOG
#ifndef LOGSYS_FLAG
#define LOGSYS_FLAG
#endif
#endif

#include <project.h>
#define CITI_C

#include <sizes.h>
#include <aclconio.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>    //liem
#include <acldev.h>
#include <aclstr.h>
#include <aclutil.h>
#include <prot8583.h>
#include <define.h>
#include <transact.h>
#include <dbmgr.h>
#include <mdlfuncs.h>
#include <svc.h>
#include <power.h> //liem

#include <entry.h>    //liem
#include <pinpad.h>   //liem
#include <protocol.h>
#include <packet.h>
#include <tran.h>
#include <comm.h>
#include <modem.h>
#include <ppt.h>
#include <piputl.h>
#include <pipmsg.h>
#include <isoutl.h>
#include <isoload.h>
#include <ifldtbl.h>
#include <msg.h>
#include <msgfuncs.h>
#include <bdt.h>
#include <hdt.h>
#include <trt.h>
#include <mht.h>
#include <iit.h>
#include <accum.h>
#include <form.h>
#include <date.h>
#include <mem.h>
#include <spdebug.h>
#include <funcids.h>
#include <pbatch.h>
#include <errno.h>
#include <ascii.h>
#include <amexhost.h>
#include <pct.h>
#include <formater.h>
#include <table.h>
#include <string.h>
#include <confio.h>
#include <aclfile.h>
#include <format.h>
#include <spamsg.h>
#include <oper.h>
#include <batmsg.h>
#include <ui.h>
#include <tct.h>
#include <multilng.h>
#include <logo.h>
#include <settlbat.h>
#include <msgclrk.h>
#include <msgshf.h>
#include <menufunc.h>
#include <mit.h>
#include <applidl.h>
#include <tblutil.h>
#include <menus.h>
#include <Validt.h>
#include <stats.h>
#include <cardmsg.h>
#include <card.h>
#include <msg.h>
#include <define.h>
#include <entry.h>
#include <pinpad.h>
#include <ctype.h>
#include <gds.h>
#include <power.h>
#include <tip.h>
#include <iso8583.h>
#include <beetle.h>
#include <xmodem.h>
#include <modemmsg.h>
#include <scdefine.h>
#include <rcptsegs.h>
#include <operate.h>
#include <cdt.h>///ivan
#include <battery.h>
#include <printer.h>
#include <rs232.h>
#include <ConfProto.h> //

#include <EMVTags.hpp>
#include <EMVTypeDefs.hpp>
#include <EMVCWrappers.h>
#include <EMVResult.hpp>
#include <Vxemvapdef.h>

#include "IMAMids.h"
#include "MiniAtm.h"
#include "UclCode.h"
#include "ImamUtil.h"
#include "ImamMenu.h"

#include "..\cpacsrc\cpacmsg.h"
#include "..\cpacsrc\cpacids.h"
#include "..\cpacsrc\cpacsrc.h"
#include "..\cpacsrc\cpac.h"
#include "..\cpacsrc\cpacsize.h"
#include "..\cpacsrc\cpacprnt.h"
#include "..\cpacsrc\cpacoper.h"

#include "..\CITIsrc\CITImsg.h"
#include "..\CITIsrc\CITIsrc.h"
#include "..\CITIsrc\CITIids.h"
#include "..\CITIsrc\CITIsize.h"

//#include "..\EPPSrc\EPPSrc.h"
//#include "..\CASHSrc\CASHSrc.h"
//#include "..\CABKSrc\CABKSrc.h"

#include "..\EMVSrc\EMVsrcdef.h"

extern int	inMAMAvailable;  //
extern VS_BOOL fDisplayIdleMenu;  //
extern int inImamUnlockKeyboard;  // Add
extern int inImamModemLowPower;
extern unsigned long lnGlobalAmount;
extern int inImamTerminalModel;
extern int inImamLineNumber;
extern int inImamRestartFlag;
extern SMenu *ImamActiveMenu;
char szImamEnterPinLabel[22];
char szImamPAN[PAN_SIZE+1];
int inDisplayResponseMode=0;

extern int inCalculatePin(unsigned char *szPAN, char * PINInput,unsigned char *ePIN);
TRANSACTION_BITMAP obTranMapCurr;
/*
//LIEM NOTE: IF VARIANT STRUCT NOT WORK ==> TRY IN DECIMAL INSTEAD OF HEXA
variant_struct ImamVariantField_60[] = {  //defined in iso8583.h
	//{0x00, 0x0220, 12, BCD_STR, VARIABLE(srISO.pszField60)},
	{0x40, 0x0100, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //PreTransfer Req
	{0x40, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //PreTRansfer Resp	
	{0x40, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Transfer Req
	{0x40, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //TRansfer Resp	
	{0x40, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //TRansfer Reversal	
	{0x50, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay CC Req
	{0x50, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay CC Resp
	{0x50, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay CC Req Reversal	
	{0x60, 0x0100, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //PrePay PLN
	{0x60, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //PrePay PLN Resp	
	{0x60, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay PLN
	{0x60, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay PLN Resp	
	{0x60, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay PLN Reversal
	{0x70, 0x0100, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //PrePay Telpon
	{0x70, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //PrePay Telpon Resp	
	{0x70, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay Telpon
	{0x70, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay Telpon Resp	
	{0x70, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay Telpon Reversal
	{0x80, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay HP Req
	{0x80, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay HP Resp	
	{0x80, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Pay HP Req Reversal
	{0x90, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Topup HP Req
	{0x90, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Topup HP Resp
	{0x90, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Topup HP Req Reversal
	{0x10, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Voucher HP Req & Debet Point
	{0x10, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Voucher HP Resp & Debet
	{0x10, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Voucher HP Req Reversal & Debet
	{0x10, 0x0300, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Reg Mobile Banking
	{0x00, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Credit Point Req
	{0x00, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Credit Point Resp
	{0x00, 0x0400, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Credit Point Req Reversal
	{0x00, 0x0220, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Offline Credit Point Req
	{0x00, 0x0230, 99, AV3_STR, VARIABLE(srISO.pszField60)},  //Offline Credit Point Resp
	{0x03, 0x0200, 99, AV3_STR, VARIABLE(srISO.pszField60)},
	{0x90, 0x0810, 99, AV3_STR, VARIABLE(srISO.pszField60)},
	{0x92+STOP, 0x0500, 6, BCD_STR, VARIABLE(srISO.pszField60)},
};

variant_struct ImamVariantField_63[] = {  //defined in iso8583.h
	{0x00, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Purchase
	{0x50, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Isi Ulang, PAYMENT
	{0x80, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Registration
	{0x31, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Info Saldo
	{0x38, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Mini Statement
	{0x39, 0x0310, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Info Credit Card
	{0x38, 0x0310, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Info Billing
	{0x40, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata TRF 2 CIF
	{0x49, 0x0210, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata TRF 2 Other Banks

	{0x00, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Purchase
	{0x50, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Isi Ulang, PAYMENT
	{0x80, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Registration
	{0x31, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Info Saldo
	{0x38, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Mini Statement
	{0x39, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Info Credit Card
	{0x38, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata Info Billing
	{0x40, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata TRF 2 CIF
	{0x49, 0x0110, 99, AV3_STR, VARIABLE(srISO.pszField63)},  //Permata TRF 2 Other Banks

	{0x80, 0x0800, 18, BCD_BCD, VARIABLE(srISO.pszField63)},
	{0x92+STOP, 0x0500, 6, BCD_STR, VARIABLE(srISO.pszField63)},
};
*/

int inMiniAtmTransactionInit(TRANSACTION_OBJECT *pobTran)
{
#ifndef IMAM_BNI
    int inHostIndex;
	int inHosts=MAX_HOSTS;
	int inRetval = VS_SUCCESS;

	//inHostIndex = 0;  //Assume host index of miniATM = 0
	inHostIndex = MAX_HOSTS-1;  //Assume EMA host index ada di Paling Belakang. Ema Host selalu ditandai sebagai ImamGuestHost agar tidak termasuk dalam Card Selection
	if (inGetMerchantNum() == 0) 
		inLoadMITRec(0);
      if (inLoadDefaultHost (inHostIndex) != VS_SUCCESS)
		return (VS_ERR);
	if (inLoadDefaultCurrency (pobTran) != VS_SUCCESS) 
		return (VS_ERR);
        vdSetHostHandle(inHostIndex);
	if (inRetval == VS_SUCCESS)
		inRetval = inCPACGetMerchEnable(pobTran);
	if (inRetval != VS_SUCCESS) {
		//if (fGetImamGuestHost()) {
		//	inRetval = VS_SUCCESS;
	//	} else {
	//		DisplayStatus("INVALID EMA HOST!");
			SVC_WAIT(2000);
			inRetval = VS_ERR;
	//	}
	}
	vdLoadCPACParams(&srCPAC);  //Must do This so can appoint correct CPAC data/Aquirer
	if (inRetval == VS_SUCCESS) { //Load MiniATM CDT
		int inRecIndex = 0;
		do {
			inRetval = inLoadCDTRec(inRecIndex);
			if( inRetval == VS_ERR ) {
				break;		
			}
			if (inGetHostIndex() == inHostIndex) {
				break;
			}		
			inRecIndex++;
		}while (1);
	}
	return inRetval;
		#else
	return VS_SUCCESS;
		#endif

		
}

int inPmtTrxPurchase(TRANSACTION_OBJECT *pobTran)
{
#ifndef IMAM_BNI
	int inRetval = VS_SUCCESS;
	IMAM_TRANSACTION_OBJECT obTranEma;
	unsigned char SentBuff[MSG_BUFF_SIZE + 1];
	unsigned char RecvBuff[MSG_BUFF_SIZE + 1];
	int inTryCounter = 0;

	memset(SentBuff, 0x00, sizeof(SentBuff));
	memset(RecvBuff, 0x00, sizeof(RecvBuff));
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		memset((void *)&obTranEma, 0x00, sizeof(obTranEma));
		memcpy((char *)&obTranEma.TrxMenu, (char *)ImamActiveMenu, sizeof(SMenu));
		obTranEma.inCode = obTranEma.TrxMenu.inCode; 
		obTranEma.inOriginalCode = obTranEma.TrxMenu.inCode; 
		vdImamGetEmaData(obTranEma.TrxMenu.inDataID, 1, buff); //Token 1 for Additional data
		strcpy(obTranEma.szAdditionalInfo, buff);
		if (inRetval == VS_SUCCESS) inRetval = inShowTitle(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inMiniAtmTransactionInit(pobTran);
		if (inRetval == VS_SUCCESS) inRetval = inImamCreateVariantTables();
	}
	if (inRetval == VS_SUCCESS) inRetval = inGetCard(&obTranEma);
	if (inRetval == VS_SUCCESS) inRetval = inBeginComm();

	if (inRetval == VS_SUCCESS) vdScrollDisplay();


	//	if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);

		if (inRetval == VS_SUCCESS) vdScrollDisplay();
		memset(obTranEma.szRespCode, 0x00, sizeof(obTranEma.szRespCode));
		memset(obTranEma.szPIN, 0x00, sizeof(obTranEma.szPIN));
		if (inRetval == VS_SUCCESS) inRetval = inImamGetEncryptedPin(&obTranEma, "ENTER PIN", pobTran);     
	//	if (inRetval == VS_SUCCESS) inRetval = inShowPobTran(&obTranEma);
		//if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inHorizontalMenuChoice("", "LANJUT", "", "", "BATAL");
		if (inRetval == 1) 
			{inRetval = VS_SUCCESS;}
              else {inRetval = VS_ERR;}	
		if (inRetval == VS_SUCCESS) DisplayStatus("  -----------------  ");
	      if (inRetval == VS_SUCCESS) vdScrollDisplay();
		if (inRetval == VS_SUCCESS) DisplayStatus("Processing...");
		//if ((inTryCounter==1) && (inRetval == VS_SUCCESS)) inRetval = SaveNewBatchRecord(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamSetBitmap(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamPackMessage(&obTranEma, SentBuff);
		if (inRetval == VS_SUCCESS) inRetval = inImamSendAndReceiveMessage(&obTranEma, SentBuff, RecvBuff, 0);  
		if (inRetval == VS_SUCCESS) inRetval = inImamUnpackAndValidateMessage(&obTranEma, RecvBuff);
	

		if (inRetval == VS_SUCCESS) inRetval = inDisplayHostResponse(&obTranEma);
		

	vdImamFreeVariantTables();
	inEndComm();
	return inRetval;
			#else
	return VS_SUCCESS;
		#endif

}

int inPmtTrxTransfer(TRANSACTION_OBJECT *pobTran)
{

#ifndef IMAM_BNI
	int inRetval = VS_SUCCESS;
	IMAM_TRANSACTION_OBJECT obTranEma;
	unsigned char SentBuff[MSG_BUFF_SIZE + 1];
	unsigned char RecvBuff[MSG_BUFF_SIZE + 1];
	int inTryCounter = 0;

	memset(SentBuff, 0x00, sizeof(SentBuff));
	memset(RecvBuff, 0x00, sizeof(RecvBuff));
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		memset((void *)&obTranEma, 0x00, sizeof(obTranEma));
		memcpy((char *)&obTranEma.TrxMenu, (char *)ImamActiveMenu, sizeof(SMenu));
		obTranEma.inCode = obTranEma.TrxMenu.inCode; 
		obTranEma.inOriginalCode = obTranEma.TrxMenu.inCode; 
		vdImamGetEmaData(obTranEma.TrxMenu.inDataID, 1, buff); //Token 1 for Additional data
		strcpy(obTranEma.szAdditionalInfo, buff);
		if (inRetval == VS_SUCCESS) inRetval = inShowTitle(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inMiniAtmTransactionInit(pobTran);
		if (inRetval == VS_SUCCESS) inRetval = inImamCreateVariantTables();
	}
	if (inRetval == VS_SUCCESS) inRetval = inGetCard(&obTranEma);
	if (inRetval == VS_SUCCESS) inRetval = inBeginComm();

	if (inRetval == VS_SUCCESS) vdScrollDisplay();


	//	if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);

		if (inRetval == VS_SUCCESS) vdScrollDisplay();
		memset(obTranEma.szRespCode, 0x00, sizeof(obTranEma.szRespCode));
		memset(obTranEma.szPIN, 0x00, sizeof(obTranEma.szPIN));
		if (inRetval == VS_SUCCESS) inRetval = inImamGetEncryptedPin(&obTranEma, "ENTER PIN", pobTran);     
	//	if (inRetval == VS_SUCCESS) inRetval = inShowPobTran(&obTranEma);
		//if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);
			if (inRetval == VS_SUCCESS) inRetval = inHorizontalMenuChoice("", "LANJUT", "", "", "BATAL");
		if (inRetval == 1) 
			{inRetval = VS_SUCCESS;}
              else {inRetval = VS_ERR;}	

		if (inRetval == VS_SUCCESS) DisplayStatus("  -----------------  ");
	      if (inRetval == VS_SUCCESS) vdScrollDisplay();
		if (inRetval == VS_SUCCESS) DisplayStatus("Processing...");
		//if ((inTryCounter==1) && (inRetval == VS_SUCCESS)) inRetval = SaveNewBatchRecord(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamSetBitmap(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamPackMessage(&obTranEma, SentBuff);
		if (inRetval == VS_SUCCESS) inRetval = inImamSendAndReceiveMessage(&obTranEma, SentBuff, RecvBuff, 0);  
		if (inRetval == VS_SUCCESS) inRetval = inImamUnpackAndValidateMessage(&obTranEma, RecvBuff);
	

		if (inRetval == VS_SUCCESS) inRetval = inDisplayHostResponse(&obTranEma);
		

	vdImamFreeVariantTables();
	inEndComm();
	return inRetval;
			#else
	return VS_SUCCESS;
		#endif


}

int inPmtTrxInfoSaldo(TRANSACTION_OBJECT *pobTran)
{
	int inRetval = VS_SUCCESS;
	IMAM_TRANSACTION_OBJECT obTranEma;
	unsigned char SentBuff[MSG_BUFF_SIZE + 1];
	unsigned char RecvBuff[MSG_BUFF_SIZE + 1];
	int inTryCounter = 0;

	memset(SentBuff, 0x00, sizeof(SentBuff));
	memset(RecvBuff, 0x00, sizeof(RecvBuff));
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		memset((void *)&obTranEma, 0x00, sizeof(obTranEma));
		memcpy((char *)&obTranEma.TrxMenu, (char *)ImamActiveMenu, sizeof(SMenu));
		obTranEma.inCode = obTranEma.TrxMenu.inCode; 
		obTranEma.inOriginalCode = obTranEma.TrxMenu.inCode; 
		vdImamGetEmaData(obTranEma.TrxMenu.inDataID, 1, buff); //Token 1 for Additional data
		strcpy(obTranEma.szAdditionalInfo, buff);
		if (inRetval == VS_SUCCESS) inRetval = inShowTitle(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inMiniAtmTransactionInit(pobTran);
		if (inRetval == VS_SUCCESS) inRetval = inImamCreateVariantTables();
	}
	//if (inRetval == VS_SUCCESS) inRetval = inGetCard(&obTranEma);
	if (inRetval == VS_SUCCESS) inRetval = inBeginComm();

	//if (inRetval == VS_SUCCESS) vdScrollDisplay();


	//	if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);

		if (inRetval == VS_SUCCESS) vdScrollDisplay();
		memset(obTranEma.szRespCode, 0x00, sizeof(obTranEma.szRespCode));

		if (inRetval == VS_SUCCESS) DisplayStatus("  -----------------  ");
	      if (inRetval == VS_SUCCESS) vdScrollDisplay();
		if (inRetval == VS_SUCCESS) DisplayStatus("Processing...");
		//if ((inTryCounter==1) && (inRetval == VS_SUCCESS)) inRetval = SaveNewBatchRecord(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamSetBitmap(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamPackMessage(&obTranEma, SentBuff);
		if (inRetval == VS_SUCCESS) inRetval = inImamSendAndReceiveMessage(&obTranEma, SentBuff, RecvBuff, 0);  
		if (inRetval == VS_SUCCESS) inRetval = inImamUnpackAndValidateMessage(&obTranEma, RecvBuff);
	

		if (inRetval == VS_SUCCESS) inRetval = inDisplayHostResponse(&obTranEma);
		

	vdImamFreeVariantTables();
	inEndComm();
	return inRetval;
		

}

int inPmtTrxMiniStatement(TRANSACTION_OBJECT *pobTran)
{

	int inRetval = VS_SUCCESS;
	IMAM_TRANSACTION_OBJECT obTranEma;
	unsigned char SentBuff[MSG_BUFF_SIZE + 1];
	unsigned char RecvBuff[MSG_BUFF_SIZE + 1];
	int inTryCounter = 0;

	memset(SentBuff, 0x00, sizeof(SentBuff));
	memset(RecvBuff, 0x00, sizeof(RecvBuff));
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		memset((void *)&obTranEma, 0x00, sizeof(obTranEma));
		memcpy((char *)&obTranEma.TrxMenu, (char *)ImamActiveMenu, sizeof(SMenu));
		obTranEma.inCode = obTranEma.TrxMenu.inCode; 
		obTranEma.inOriginalCode = obTranEma.TrxMenu.inCode; 
		vdImamGetEmaData(obTranEma.TrxMenu.inDataID, 1, buff); //Token 1 for Additional data
		strcpy(obTranEma.szAdditionalInfo, buff);
		if (inRetval == VS_SUCCESS) inRetval = inShowTitle(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inMiniAtmTransactionInit(pobTran);
		if (inRetval == VS_SUCCESS) inRetval = inImamCreateVariantTables();
	}
	//if (inRetval == VS_SUCCESS) inRetval = inGetCard(&obTranEma);
	if (inRetval == VS_SUCCESS) inRetval = inBeginComm();

	//if (inRetval == VS_SUCCESS) vdScrollDisplay();


	//	if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);

		if (inRetval == VS_SUCCESS) vdScrollDisplay();
		memset(obTranEma.szRespCode, 0x00, sizeof(obTranEma.szRespCode));
		memset(obTranEma.szPIN, 0x00, sizeof(obTranEma.szPIN));
	//	if (inRetval == VS_SUCCESS) inRetval = inImamGetEncryptedPin(&obTranEma, "ENTER PIN", pobTran);     
		//if (inRetval == VS_SUCCESS) inRetval = inShowPobTran(&obTranEma);
	//	if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);

		if (inRetval == VS_SUCCESS) DisplayStatus("  -----------------  ");
	      if (inRetval == VS_SUCCESS) vdScrollDisplay();
		if (inRetval == VS_SUCCESS) DisplayStatus("Processing...");
		//if ((inTryCounter==1) && (inRetval == VS_SUCCESS)) inRetval = SaveNewBatchRecord(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamSetBitmap(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamPackMessage(&obTranEma, SentBuff);
		if (inRetval == VS_SUCCESS) inRetval = inImamSendAndReceiveMessage(&obTranEma, SentBuff, RecvBuff, 0);  
		if (inRetval == VS_SUCCESS) inRetval = inImamUnpackAndValidateMessage(&obTranEma, RecvBuff);
	

		if (inRetval == VS_SUCCESS) inRetval = inDisplayHostResponse(&obTranEma);
		

	vdImamFreeVariantTables();
	inEndComm();
	return inRetval;
	
}

int inPmtTrxInfoCreditCard(TRANSACTION_OBJECT *pobTran)
{

	int inRetval = VS_SUCCESS;
	IMAM_TRANSACTION_OBJECT obTranEma;
	unsigned char SentBuff[MSG_BUFF_SIZE + 1];
	unsigned char RecvBuff[MSG_BUFF_SIZE + 1];
	int inTryCounter = 0;

	memset(SentBuff, 0x00, sizeof(SentBuff));
	memset(RecvBuff, 0x00, sizeof(RecvBuff));
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		memset((void *)&obTranEma, 0x00, sizeof(obTranEma));
		memcpy((char *)&obTranEma.TrxMenu, (char *)ImamActiveMenu, sizeof(SMenu));
		obTranEma.inCode = obTranEma.TrxMenu.inCode; 
		obTranEma.inOriginalCode = obTranEma.TrxMenu.inCode; 
		vdImamGetEmaData(obTranEma.TrxMenu.inDataID, 1, buff); //Token 1 for Additional data
		strcpy(obTranEma.szAdditionalInfo, buff);
		if (inRetval == VS_SUCCESS) inRetval = inShowTitle(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inMiniAtmTransactionInit(pobTran);
		if (inRetval == VS_SUCCESS) inRetval = inImamCreateVariantTables();
	}
	if (inRetval == VS_SUCCESS) inRetval = inGetCard(&obTranEma);
	if (inRetval == VS_SUCCESS) inRetval = inBeginComm();

	if (inRetval == VS_SUCCESS) vdScrollDisplay();


		//if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);

		if (inRetval == VS_SUCCESS) vdScrollDisplay();
		memset(obTranEma.szRespCode, 0x00, sizeof(obTranEma.szRespCode));
		memset(obTranEma.szPIN, 0x00, sizeof(obTranEma.szPIN));
		if (inRetval == VS_SUCCESS) inRetval = inImamGetEncryptedPin(&obTranEma, "ENTER PIN", pobTran);     
		//if (inRetval == VS_SUCCESS) inRetval = inShowPobTran(&obTranEma);
	//	if (inRetval == VS_SUCCESS) vdDisplayFee(&obTranEma);
	
		if (inRetval == VS_SUCCESS) inRetval = inHorizontalMenuChoice("", "LANJUT", "", "", "BATAL");
		if (inRetval == 1) 
			{inRetval = VS_SUCCESS;}
              else {inRetval = VS_ERR;}	

		if (inRetval == VS_SUCCESS) DisplayStatus("  -----------------  ");
	      if (inRetval == VS_SUCCESS) vdScrollDisplay();
		if (inRetval == VS_SUCCESS) DisplayStatus("Processing...");
		//if ((inTryCounter==1) && (inRetval == VS_SUCCESS)) inRetval = SaveNewBatchRecord(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamSetBitmap(&obTranEma);
		if (inRetval == VS_SUCCESS) inRetval = inImamPackMessage(&obTranEma, SentBuff);
		if (inRetval == VS_SUCCESS) inRetval = inImamSendAndReceiveMessage(&obTranEma, SentBuff, RecvBuff, 0);  
		if (inRetval == VS_SUCCESS) inRetval = inImamUnpackAndValidateMessage(&obTranEma, RecvBuff);
	

		if (inRetval == VS_SUCCESS) inRetval = inDisplayHostResponse(&obTranEma);
		

	vdImamFreeVariantTables();
	inEndComm();
	return inRetval;

}


int inImamPowerOff(TRANSACTION_OBJECT *pobTran)
{
#ifndef IMAM_BNI
	int inRetval;
	inRetval = inMenuChoice("TURN OFF?", "RESTART", "TURN OFF", "", "");
	clrscr();
	LOG_PRINTFF((0x08L, "Select = [%d]", inRetval));
	if (inRetval<1 || inRetval>2) return (VS_SUCCESS);

	if ((inRetval==2) && (get_dock_status()==HANDHELD_UNDOCKED)){
		DisplayStatus("RELEASE COMM...");
		inImamReleaseComm();
		DisplayStatus("RELEASE COMM...[OK]");
		vdScrollDisplay();
		DisplayStatus("SHUTTING DOWN...");
		SVC_SHUTDOWN();
	} else if (inRetval==1){
		DisplayStatus("RELEASE COMM...");
		inImamReleaseComm();
		DisplayStatus("RELEASE COMM...[OK]");
		vdScrollDisplay();
		DisplayStatus("RESTARTING...");
		SVC_WAIT(2000);
		SVC_RESTART("");
	} else {
		if (inRetval==2){
			DisplayStatus("UNABLE TO TURN OFF");
		}
	}
	SVC_WAIT(2000);
	return VS_SUCCESS;
	#else
	return VS_SUCCESS;
		#endif

}



int inImamClearBatch(TRANSACTION_OBJECT *pobTran)
{
#ifndef IMAM_BNI
	int inRetval = VS_SUCCESS;
	int fhandle;
	int bytes, i;
	int found = 0;
	long countbyte;
	IMAM_TRANSACTION_OBJECT obTranEma;
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		memset((void *)&obTranEma, 0x00, sizeof(obTranEma));
		memcpy((char *)&obTranEma.TrxMenu, (char *)ImamActiveMenu, sizeof(SMenu));
		obTranEma.inCode = obTranEma.TrxMenu.inCode; 
		obTranEma.inOriginalCode = obTranEma.TrxMenu.inCode; 
		vdImamGetEmaData(obTranEma.TrxMenu.inDataID, 1, buff); //Token 1 for Additional data
		strcpy(obTranEma.szAdditionalInfo, buff);
		if (inRetval == VS_SUCCESS) inRetval = inShowTitle(&obTranEma);
	}	
	fhandle = open(IMAM_EMA_BATCH, O_RDWR);
	if (fhandle == -1) return VS_ERR;

	for (i=0; i<BATCH_SIZE; i++) {
		obTranEma.RecordNo = 0;
		countbyte = write(fhandle, (const void *)&obTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
		if (countbyte != sizeof(IMAM_TRANSACTION_OBJECT)) {
			DisplayStatus("Not Enough Memory!");
			while(1);
		}
	}
	
	close(fhandle);
	DisplayStatus("Successfully Cleared");
	SVC_WAIT(1000);
	return VS_SUCCESS;
	#else
	return VS_SUCCESS;
		#endif
}

int inShowTitle(IMAM_TRANSACTION_OBJECT *pobTranEma)
{
  #ifndef IMAM_BNI
	char msgbuff[22];
	char msg[22];
	int i=0;

	memset(msg, 0x00, sizeof(msg));
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		vdImamGetEmaData(pobTranEma->TrxMenu.inDataID, 2, buff);  //Token 2 for MenuName
		strncpy(msg, buff, 22);
	}
	if (strlen(msg)==0) {				//get Name of SMENU to display
		strcpy(msg, pobTranEma->TrxMenu.Name);
	}
	if (strlen(msg)>21) {
		strncpy(msgbuff, msg, 21);
		msg[21] = 0x00;
	} else if (strlen(msg)){
		strcpy(msgbuff, msg);
	}
	DisplayJudul(msgbuff);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inGetCard(IMAM_TRANSACTION_OBJECT *pobTranEma)
{
#ifndef IMAM_BNI
	int inResult=VS_SUCCESS;
	do {
		inResult = inGetCardInside(pobTranEma);		
		if (inResult==1) 
			inResult=VS_SUCCESS;
		if (inResult==-1) 
			inResult=VS_ERR;
		break;
	} while (1);
	
	return inResult;
	#else
	return VS_SUCCESS;
		#endif

}

int inGetCardInside(IMAM_TRANSACTION_OBJECT *pobTranEma)
{

#ifndef IMAM_BNI
    int i;
	int     kar;

	short	shRetVal = 0 ;
    char	szRawCardData[CARD_SIZE] ;

	struct	TRACK stParsedCardData ;	// Card Data Holder

	ClearSevenLine();
	//write_at("Enter Card Number or", 20, 1, inImamLineNumber/2);  //display logo swipe here if needed
	write_at(" Swipe Customer Card", 20, 1, inImamLineNumber/2 + 1);
	TimeOut(15000);
	do {
		if (card_pending()==1) {
			break;
		}
		if (KBHIT()){
			int inKeyPressResult = inGetCardManual(pobTranEma);
			if (inKeyPressResult==0) { 
				ClearSevenLine(); 
				return 0;
			} else if (inKeyPressResult==-1) {
				return -1;
			}else {
				return inCheckCard(pobTranEma);
			}
		}
		//if (TimeOut(0)) return 0;
		if (TimeOut(0)) return -1;
		SVC_WAIT(0);
	}while (1);

	shRetVal = read(hCardReader, szRawCardData, sizeof(szRawCardData)) ;
    if(shRetVal < 0)
	{
		//DisplayStatus("Can't read Card Data");
		DisplayStatus("SWIPE ERR. TRY AGAIN");
		vdWarnBeep();
		SVC_WAIT(2000);
		DisplayStatus("");
        return 0 ;
	}
	//parse the card data
	shRetVal = card_parse(szRawCardData, &stParsedCardData, "1") ;
	if (shRetVal == 1) {
		strcpy(pobTranEma->szCHolder, stParsedCardData.name);
	}
    shRetVal = card_parse(szRawCardData, &stParsedCardData, "2") ;
    if(shRetVal != 2)
	{
		//DisplayStatus("Error in Card Parsing");
		DisplayStatus("SWIPE ERR. TRY AGAIN");
		vdWarnBeep();
  		SVC_WAIT(2000);
		DisplayStatus("");
        return 0 ;
	}
	while (1) {  //trimspace
		if (strlen(pobTranEma->szCHolder)==0) {
			strcpy(pobTranEma->szCHolder, "-");
			break;
		} else if (isspace(pobTranEma->szCHolder[strlen(pobTranEma->szCHolder)-1])) {
			pobTranEma->szCHolder[strlen(pobTranEma->szCHolder)-1] = 0x00;
		} else {
			break;
		}
	}
	strcpy(pobTranEma->szPAN, stParsedCardData.acct);
	strcpy(pobTranEma->szExpDate, stParsedCardData.exp);
	if (card_parse(szRawCardData, &stParsedCardData, "2")==2) {
		strcpy(pobTranEma->stT2Data, stParsedCardData.track);
	} else {
        //DisplayStatus("Invalid Track2 Data");
		DisplayStatus("SWIPE ERR. TRY AGAIN");
		vdWarnBeep();
  		SVC_WAIT(2000);
		DisplayStatus("");
		return 0;
	}
	LOG_PRINTFF((0x08L, "Parsed Track2 (%d) = %s", strlen(stParsedCardData.track), stParsedCardData.track));
	sprintf((char *)pobTranEma->stT2DataImam,"%s" ,stParsedCardData.track);
	
	
	for (i=0; i<inImamLineNumber-1; i++) vdScrollDisplay();
    if (strlen(pobTranEma->szCHolder)>0) {
		char buff[22];
		display_at(1, inImamLineNumber-2, "PAN", CLR_EOL);
		display_at(22-strlen(pobTranEma->szPAN), inImamLineNumber-2, pobTranEma->szPAN, CLR_EOL);
		memset(buff, 0x00, sizeof(buff));
		strncat(buff, &pobTranEma->szExpDate[2], 2);
		strncat(buff, &pobTranEma->szExpDate[0], 2);
		display_at(1, inImamLineNumber-1, "EXP.(MMYY)", CLR_EOL);
		display_at(22-strlen(buff), inImamLineNumber-1, buff, CLR_EOL);
		//vdScrollDisplay();
		//memset(buff, 0x00, sizeof(buff));
		//strncpy(buff, pobTranEma->szCHolder, 21);
		//display_at(1, inImamLineNumber-1, "Name", CLR_EOL);
		//display_at(22-strlen(buff), inImamLineNumber-1, buff, CLR_EOL);
	} else {
		char buff[22];
		display_at(1, inImamLineNumber-2, "PAN", CLR_EOL);
		display_at(22-strlen(pobTranEma->szPAN), inImamLineNumber-2, pobTranEma->szPAN, CLR_EOL);
		memset(buff, 0x00, sizeof(buff));
		strncat(buff, &pobTranEma->szExpDate[2], 2);
		strncat(buff, &pobTranEma->szExpDate[0], 2);
		display_at(1, inImamLineNumber-1, "EXP.(MMYY)", CLR_EOL);
		display_at(22-strlen(buff), inImamLineNumber-1, buff, CLR_EOL);
	}
    //display_at(1, 4, "Exp on :", CLR_EOL);
    //display_at(9, 4, stParsedCardData.exp, CLR_EOL);
	return inCheckCard(pobTranEma);
		#else
	return VS_SUCCESS;
		#endif

}

int inGetCardManual(IMAM_TRANSACTION_OBJECT *pobTranEma)
{
#ifndef IMAM_BNI
	char buff[128];
	long Acct;
	int i;
	int inManualAllowed;

	ClearSevenLine();
	{
		char buff[128];
		memset(buff, 0x00, sizeof(buff));
		vdImamGetEmaData(pobTranEma->TrxMenu.inDataID, 0, buff); //Token 0 for ManualAllow flag
		inManualAllowed = atoi(buff);
	}
	if (inManualAllowed == 0){  //Need to check this code again if we allow manual
		if (get_char() != 27) {
			DisplayStatus("Swipe Only!");
			SVC_WAIT(1000);
			
			return -1;
		}
		return -1;  //cancel key presse
	}

	while (1) {
	   memset(buff, 0x00, sizeof(buff));
	   if (InputPAN("PAN", buff, 1L, (long)9999999999L, 0, &Acct) == 0) return 0;
	   //if (InputNumber("PAN", buff, 1L, (long)9999999999L, 0, &Acct) == 0) return 0;
	   if (strlen(buff)>=12 && strlen(buff)<=PAN_SIZE) {
	      strcpy(pobTranEma->szPAN, buff);   
		  break;
	   }
	   DisplayStatus("Invalid PAN Input!");
	   SVC_WAIT(500);
	   display_at( 1, inImamLineNumber-1,"", CLR_EOL);
	   ClearStatusLine();
	}
	vdScrollDisplay();
	while (1) {
	   memset(buff, 0x00, sizeof(buff));
	   if (InputNumberEngl("EXP.(MMYY)", buff, 1L, (long)9999999999L, 0, &Acct) == 0) return 0;
	   if (strlen(buff)==EXP_DATE_SIZE) {
	      strncpy(&pobTranEma->szExpDate[0], &buff[2], 2);
		  strncpy(&pobTranEma->szExpDate[2], &buff[0], 2);
		  pobTranEma->szExpDate[4] = 0x00;
		  break;
	   }
	   DisplayStatus("Must 4 Digit!");
	   SVC_WAIT(500);
	   display_at( 1, inImamLineNumber-1,"", CLR_EOL);
	   ClearStatusLine();
	}
	pobTranEma->inManual=1;
	return 1;
			#else
	return VS_SUCCESS;
		#endif

}

int inCheckCard(IMAM_TRANSACTION_OBJECT *pobTranEma)
{
#ifndef IMAM_BNI
	char Buff[20];
	char CurrDate[5];
	char CardBin[20];
	int i;
	memset(Buff, 0x00, sizeof(Buff));
	memset(CardBin, 0x00, sizeof(CardBin));
	SVC_CLOCK(0, Buff, 15);
		
	strncpy(CurrDate, &Buff[2], 4);
	CurrDate[4] = 0x00;

	if (strcmp(CurrDate, pobTranEma->szExpDate)>0) {
		DisplayStatus("EXPIRED CARD!");
		vdWarnBeep();
		SVC_WAIT(1000);
		return 0;
	}
//  bin checking
	pobTranEma->isOnUs = 0;
	for (i=0; i<20; i++) {
	   memset(Buff, 0x00, sizeof(Buff));
	   get_env_x(HOST_CARD_ONUS, i, Buff);
	   if (!strncmp(Buff, pobTranEma->szPAN, strlen(Buff))) {
		   pobTranEma->isOnUs = 1;
		   break;
		  //return 1;
	   }
	}

	if (pobTranEma->isOnUs==0) {
		memset(Buff, 0x00, sizeof(Buff));
		get_env_x(TXR_OFFUS, 0, Buff);		
		if (atoi(Buff)==0) {
			if (pobTranEma->inOriginalCode == PMT_TRX_ISI_ULANG
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_TELPON
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_PLN
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_PALYJA
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_PAM
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_CDTCARD
				|| pobTranEma->inOriginalCode == PMT_TRX_CICILAN_ACC
				|| pobTranEma->inOriginalCode == PMT_TRX_CICILAN_FIF
				|| pobTranEma->inOriginalCode == PMT_TRX_CICILAN_TAF
				|| pobTranEma->inOriginalCode == PMT_TRX_CICILAN_SCB
				|| pobTranEma->inOriginalCode == PMT_TRX_CICILAN_CITI
				|| pobTranEma->inOriginalCode == PMT_TRX_CICILAN_ADIRA
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_PENDIDIKAN
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_ASURANSI
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_TIKET
				|| pobTranEma->inOriginalCode == PMT_TRX_BAYAR_PAYID) {
				DisplayStatus("CARD NOT ALLOWED!");
				vdWarnBeep();
				SVC_WAIT(1000);
				return 0;
			}
		}
	}

	if ((strcmp(pobTranEma->szPAN, "000000")<=0) || (strcmp("99999:", pobTranEma->szPAN)<=0)) { //()*+'-./0123456789:;<=>?@A...
		DisplayStatus("UNAUTHORIZED CARD!");
		vdWarnBeep();
		SVC_WAIT(1000);
		return 0;
	}
	return 1;
		#else
	return VS_SUCCESS;
		#endif

}


int inImamGetAmount(IMAM_TRANSACTION_OBJECT *pobTranEma, char *Msg)
{
#ifndef IMAM_BNI
	char buff[22];
	long Amt = 0L;
	memset(buff, 0x00, sizeof(buff));
	if (InputNumberInd(Msg, buff, 1L, (long)999999999L, 1, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
	pobTranEma->Amt = Amt;
	pobTranEma->Total = pobTranEma->Amt;
	memset(pobTranEma->szTotal, 0x00, sizeof(pobTranEma->szTotal));
	sprintf(pobTranEma->szTotal, "%ld00", pobTranEma->Total);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inImamGetAmountForBillPayment(IMAM_TRANSACTION_OBJECT *pobTranEma, char *Msg)
{
#ifndef IMAM_BNI
	char buff[22];
	char szCurrMsg[10];
	long Amt = 0L;
	memset(buff, 0x00, sizeof(buff));
	memset(szCurrMsg, 0x00, sizeof(szCurrMsg));

	strcpy(szCurrMsg, "AMT  ");
	vdGetCurrency(&szCurrMsg[5], &pobTranEma->szF48[60+F48_ADD_SIZE]);
	szCurrMsg[8]=0x00;

	if (!strcmp(&szCurrMsg[5], "RP.")) {
		if (InputNumberInd(szCurrMsg, buff, 1L, atol(pobTranEma->szTotal), 1, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
		memset(pobTranEma->szTotal, 0x00, sizeof(pobTranEma->szTotal));
		sprintf(pobTranEma->szTotal, "%ld00", Amt);
		pobTranEma->Amt = Amt;
		pobTranEma->Total = pobTranEma->Amt;
	} else {
		if (InputNumberWithCentEngl(szCurrMsg, buff, 1L, atol(pobTranEma->szTotal), 1, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
		memset(pobTranEma->szTotal, 0x00, sizeof(pobTranEma->szTotal));
		sprintf(pobTranEma->szTotal, "%ld", Amt);
		pobTranEma->Amt = Amt/100L;
		pobTranEma->Total = pobTranEma->Amt;
	}
	return VS_SUCCESS;
 	#else
	return VS_SUCCESS;
		#endif

	
}

int inGetGeneralInputNumber_1(IMAM_TRANSACTION_OBJECT *pobTranEma, char *Msg, int MinDigit, int MaxDigit)
{
#ifndef IMAM_BNI
	char buff[22];
	long Amt = 0L;
	memset(buff, 0x00, sizeof(buff));
	if (InputNumberInd(Msg, buff, MinDigit, MaxDigit, 3, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
	strcpy(pobTranEma->szInputNumber_1, buff);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inGetGeneralInputNumber_2(IMAM_TRANSACTION_OBJECT *pobTranEma, char *Msg, int MinDigit, int MaxDigit)
{
#ifndef IMAM_BNI
	char buff[22];
	long Amt = 0L;
	memset(buff, 0x00, sizeof(buff));
	if (InputNumberInd(Msg, buff, MinDigit, MaxDigit, 3, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
	strcpy(pobTranEma->szInputNumber_2, buff);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inGetGeneralInputNumber_3(IMAM_TRANSACTION_OBJECT *pobTranEma, char *Msg, int MinDigit, int MaxDigit)
{
#ifndef IMAM_BNI
	char buff[22];
	long Amt = 0L;
	memset(buff, 0x00, sizeof(buff));
	if (InputNumberInd(Msg, buff, MinDigit, MaxDigit, 3, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
	strcpy(pobTranEma->szInputNumber_3, buff);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inGetVoucherAmt(IMAM_TRANSACTION_OBJECT *pobTranEma, char *Msg)
{
#ifndef IMAM_BNI
	char buff[22];
	long Amt = 0L;
	memset(buff, 0x00, sizeof(buff));
	if (InputNumberInd(Msg, buff, 1L, (long)999999999L, 1, &Amt) == 0) return VS_ERR;  //hati-hati batas atas
	pobTranEma->lnVoucherAmt = Amt;
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inImamGetEncryptedPin(IMAM_TRANSACTION_OBJECT *pobTranEma, char *EnterPinLabel, TRANSACTION_OBJECT *pobTran)
{

	int inResult;
	char buff[20];
	char buff2[20];
	char szcurrPin[9];
	
	
	memset(szcurrPin,0x00,sizeof szcurrPin);
	memset(buff, 0x00, sizeof(buff));
  memset(buff2,0x00,sizeof buff2);

	
	if (pobTranEma->inCode ==PMT_TRX_TRANSFER)
		{
		   if (InputPIN("Current PIN:", (char *)szcurrPin, 4, 6) == 0) 
		   	return VS_ABORT;
		     memcpy( pobTranEma->szPIN2,szcurrPin, 8);
		}

	  if (InputPIN("Enter New PIN:", (char *)buff, 4, 6) == 0) 
	  	return VS_ABORT;
	{
	   if (InputPIN("Verify New PIN:", (char *)buff2, 4, 6) == 0) 
	   	return VS_ABORT;
		{  	
			if (memcmp(buff,buff2,8)!=0)
				{
					
				DisplayStatus("PIN NOT MATCH  !");
			        vdWarnBeep();
		
	        		 return (VS_ERR);
				}
			  memcpy( pobTranEma->szPIN,buff, 8);
			 	
			}
		}


	  

return VS_SUCCESS;


}

int inImamSetBitmap(IMAM_TRANSACTION_OBJECT *pobTranEma)
{

#ifndef IMAM_BNI
	int i;

	int nbyte;
	char buff[128];
	char BmpBuff[128];

	memset((char *)&obTranMapCurr, 0x00, sizeof(obTranMapCurr));
	memset(BmpBuff, 0x00, sizeof(BmpBuff));
	if (pobTranEma->inCode == PMT_TRX_PURCHASE)
		{
		 strncpy(obTranMapCurr.szMsgID, "0200", 4);
		  strncpy(obTranMapCurr.szProcCode,"940105", 6);
		   strncpy((char *)obTranMapCurr.bitmap, "6038040008C10000", 16);
		
		}
		if (pobTranEma->inCode ==PMT_TRX_TRANSFER)
		{
				 strncpy(obTranMapCurr.szMsgID, "0200", 4);
				  strncpy(obTranMapCurr.szProcCode,"940109", 6);
				   strncpy((char *)obTranMapCurr.bitmap, "6038040008C11000", 16);

		}
		if (pobTranEma->inCode==PMT_TRX_INFO_SALDO)
		{
		 		strncpy(obTranMapCurr.szMsgID, "0800", 4);
				  strncpy(obTranMapCurr.szProcCode,"900000", 6);
				   strncpy((char *)obTranMapCurr.bitmap, "2220000000C00000", 16);
		 
		}
		if (pobTranEma->inCode==PMT_TRX_MINI_STATEMENT)
		{
		                strncpy(obTranMapCurr.szMsgID, "0800", 4);
				  strncpy(obTranMapCurr.szProcCode,"920000", 6);
				   strncpy((char *)obTranMapCurr.bitmap, "2220000000C00000", 16);
		 
		}
		if (pobTranEma->inCode==PMT_TRX_INFO_CDTCARD)
		{               strncpy(obTranMapCurr.szMsgID, "0200", 4);
				  strncpy(obTranMapCurr.szProcCode,"950105", 6);
				   strncpy((char *)obTranMapCurr.bitmap, "7238440180C01000", 16);
		 
		}
	
	memset(buff, 0x00, sizeof(buff));
		nbyte = strlen((char *)obTranMapCurr.bitmap)/2;
		SVC_DSP_2_HEX((char *)obTranMapCurr.bitmap, buff, nbyte);  //asc to bcd
		memset(obTranMapCurr.bitmap, 0x00, sizeof(obTranMapCurr.bitmap));
		memcpy((char *)obTranMapCurr.bitmap, buff, nbyte);
	
	//Customisasi Bitmap Start Here
	return VS_SUCCESS;
			#else
	return VS_SUCCESS;
		#endif

}

//GET FROM EDIT_ACCUIRER TABLE : CITI.TXT
int inImamPackMessage(IMAM_TRANSACTION_OBJECT *pobTranEma, unsigned char *SentBuff)
{
#ifndef IMAM_BNI

	int PacketSize;
	char buff[128];
	char TimeBuff[15];
	char szTrack2Data[50];
	char buffer[128];
	char bufftmp[128];
	int i, j=0;
	int ni=0;
	int inRetVal = 0;
	char mode[3];
	int encmode=0;
	int dbtpdu=0;
	char pin_1[16+1];
	char pin_2[16+1];
	unsigned char unbuff[MSG_BUFF_SIZE];
	memset(unbuff,0x00,sizeof unbuff);
		
	
	memset(buffer, 0x00, sizeof(buffer));

	inRetVal= get_env("ENCMODE", mode, sizeof(mode)-1);
	encmode=atoi(mode);
   	inRetVal= get_env("DBTPDU", mode, sizeof(mode)-1);
	dbtpdu=atoi(mode);
   
	
	memset(szTrack2Data,0x00,sizeof szTrack2Data);


   if (pobTranEma->inCode==PMT_TRX_INFO_CDTCARD)
   	{

	  {
		strcpy((char *)tpdu, (char *)szGetCPACTPDU()); //TPDU


		memset(buff, 0x00, sizeof(buff));
		memset(Mti, 0x00, MTI_SIZE);
		strcpy(buff, obTranMapCurr.szMsgID);				//ok
		SVC_DSP_2_HEX(buff, (char *)Mti, MTI_SIZE); 

		strcpy((char *)srISO.pszField02, pobTranEma->szPAN);					//ok
		memset(buff, 0x00, sizeof(buff));
		memset(srISO.pszField03, 0x00, sizeof(srISO.pszField03));
		strcpy(buff, obTranMapCurr.szProcCode);				//ok
		SVC_DSP_2_HEX(buff, (char *)srISO.pszField03, PROC_CODE_SIZE);

		sprintf((char *)srISO.pszField04, "%06ld", 0L);

             memset(TimeBuff, 0x00, sizeof(TimeBuff));
		SVC_CLOCK(0, TimeBuff, 15);// read

		strncpy ((char *)srISO.pszField07,&TimeBuff[4],10);	
		
		srISO.lnField11 =lnGetAndIncStanNum(); //pobTranEma->STAN;
		strncpy((char *)pobTranEma->szDate, &TimeBuff[2], 6);
		pobTranEma->szDate[6] = 0x00;
		strncpy((char *)pobTranEma->szTime, &TimeBuff[8], 6);
		pobTranEma->szTime[6] = 0x00;
		strncpy((char *)pobTranEma->szRetRefNum,&TimeBuff[1],12);
			
		strcpy ((char *)srISO.pszField12, pobTranEma->szTime);					//ok
		strcpy ((char *)srISO.pszField13, &pobTranEma->szDate[2]);				//ok
		strcpy ((char *)srISO.pszField18, "6014");	
	
		   strcpy ((char *)srISO.pszField22, SWIPE_POS_ENTRY_CODE);			//ok

		memcpy(szTrack2Data,pobTranEma->stT2Data,TRACK2_SIZE);
		
		strcpy ((char *)srISO.pszField32, "1002");	
		strcpy ((char *)srISO.pszField33,"1002");	
	
		strcpy((char *)srISO.pszField41, (char *)szGetCPACTID());
		LOG_PRINTFF((0x08L, "PAckage TID = %s", (char *)srISO.pszField41));
		strcpy((char *)srISO.pszField42, (char *)szGetCPACMID());
		LOG_PRINTFF((0x08L, "PAckage MID = %s", (char *)srISO.pszField42));
	
              if (encmode)
              	{
			  
				
	inCalculatePin((unsigned char *)pobTranEma->szPAN, pobTranEma->szPIN, (unsigned char *)pin_1);
		//inCalculatePin((unsigned char *)pobTranEma->szPAN, pobTranEma->szPIN2,(unsigned char *) pin_2);
              	}
		else
			{ memcpy(pin_1, pobTranEma->szPIN, 8);		
		 	  // memcpy(pin_2, pobTranEma->szPIN2, 8);				//ok

			}
		 memcpy((char *)srISO.pszField52,pin_1, 16);		
		 	  // memcpy((char *)srISO.pszField52, pin_2, 16);
		
	}
	


      // just manipulate in here
      if (dbtpdu)
      	{

		
      	   PacketSize = process_8583(0, srBaseIsoFDT, obTranMapCurr.bitmap, unbuff, MSG_BUFF_SIZE-3);  //to pack
      	   memcpy(&SentBuff[2],&unbuff[5],PacketSize-5);
      	   
		   
			if (PacketSize>0) {
				SentBuff[0] = (PacketSize -5) / 256;
				SentBuff[1] = (PacketSize-5) % 256;
			}
      	   }
	  else
	  	{
	  	 	PacketSize = process_8583(0, srBaseIsoFDT, obTranMapCurr.bitmap, &SentBuff[2], MSG_BUFF_SIZE-3);  //to pack
			if (PacketSize>0) {
				SentBuff[0] = PacketSize / 256;
				SentBuff[1] = PacketSize % 256;
			}

	  	}
	LOG_PRINTFF((0x08L, "Packet Size = %d", PacketSize));
   	}
else
{
/////////////////////
	{
		strcpy((char *)tpdu, (char *)szGetCPACTPDU()); //TPDU


		memset(buff, 0x00, sizeof(buff));
		memset(Mti, 0x00, MTI_SIZE);
		strcpy(buff, obTranMapCurr.szMsgID);				//ok
		SVC_DSP_2_HEX(buff, (char *)Mti, MTI_SIZE); 

		strcpy((char *)srISO.pszField02, pobTranEma->szPAN);					//ok
		memset(buff, 0x00, sizeof(buff));
		memset(srISO.pszField03, 0x00, sizeof(srISO.pszField03));
		strcpy(buff, obTranMapCurr.szProcCode);				//ok
		SVC_DSP_2_HEX(buff, (char *)srISO.pszField03, PROC_CODE_SIZE);

		sprintf((char *)srISO.pszField04, "%06ld", 0L);

             memset(TimeBuff, 0x00, sizeof(TimeBuff));
		SVC_CLOCK(0, TimeBuff, 15);// read

		strncpy ((char *)srISO.pszField07,&TimeBuff[4],10);	
		
		srISO.lnField11 =lnGetAndIncStanNum(); //pobTranEma->STAN;
		strncpy((char *)pobTranEma->szDate, &TimeBuff[2], 6);
		pobTranEma->szDate[6] = 0x00;
		strncpy((char *)pobTranEma->szTime, &TimeBuff[8], 6);
		pobTranEma->szTime[6] = 0x00;
		strncpy((char *)pobTranEma->szRetRefNum,&TimeBuff[1],12);
		strncpy ((char *)srISO.pszField37, pobTranEma->szRetRefNum,RET_REF_SIZE);
		
		strcpy ((char *)srISO.pszField12, pobTranEma->szTime);					//ok
		strcpy ((char *)srISO.pszField13, &pobTranEma->szDate[2]);				//ok
		strcpy ((char *)srISO.pszField14, pobTranEma->szExpDate);				//ok
		strcpy ((char *)srISO.pszField18, "6014");	
	
		   strcpy ((char *)srISO.pszField22, SWIPE_POS_ENTRY_CODE);			//ok

		strcpy((char *)srISO.pszField24, (char *)szGetCPACNII());  //NII	
           // memcpy((char *) srISO.pszField35, szTrack2Data, TRACK2_SIZE);

		memcpy(szTrack2Data,pobTranEma->stT2Data,TRACK2_SIZE);
		//memcpy ((char *)srISO.pszField35, szTrack2Data, TRACK2_SIZE);  //ok
		// memcpy((char *)srISO.pszField35, pobTranEma->stT2Data, TRACK2_SIZE);
		// strcpy((char *)srISO.pszField35, "424242424242424242=9912");//, strlen("424242424242424242=9912"));

		//memcpy((char *) srISO.pszField35, szTrack2Data, TRACK2_SIZE);

		LOG_PRINTFF((0x08L, "Track 2 %s",(char *)srISO.pszField35));
		

		
		strcpy ((char *)srISO.pszField32, "1002");	
		strcpy ((char *)srISO.pszField33,"1002");	
	
		strncpy ((char *)srISO.pszField37, pobTranEma->szRetRefNum,RET_REF_SIZE);			//ok for VOID
    		strcpy ((char *)srISO.pszField38, pobTranEma->szAuthCode);				//ok for Offline refund
    		pad ((char *)srISO.pszField38,(char *)srISO.pszField38,0x20,AUTH_CODE_SIZE,LEFT); //powerfull function 0x20=SPACE
	

		strcpy((char *)srISO.pszField41, (char *)szGetCPACTID());
		LOG_PRINTFF((0x08L, "PAckage TID = %s", (char *)srISO.pszField41));
		strcpy((char *)srISO.pszField42, (char *)szGetCPACMID());
		LOG_PRINTFF((0x08L, "PAckage MID = %s", (char *)srISO.pszField42));
	
              if (encmode)
              	{
			  
				
		inCalculatePin((unsigned char *)pobTranEma->szPAN, pobTranEma->szPIN, (unsigned char *)pin_1);
		inCalculatePin((unsigned char *)pobTranEma->szPAN, pobTranEma->szPIN2,(unsigned char *) pin_2);
              	}
		else
			{ memcpy(pin_1, pobTranEma->szPIN, 8);		
		 	   memcpy(pin_2, pobTranEma->szPIN2, 8);				//ok

			}
		 memcpy((char *)srISO.pszField48,pin_1, 16);		
		 	   memcpy((char *)srISO.pszField52, pin_2, 16);
		
	}
	
	LOG_PRINTFF((0x08L, "pobTranEma Track2 (%d) = %s", strlen(pobTranEma->stT2Data), pobTranEma->stT2Data));

      // just manipulate in here
      if (dbtpdu)
      	{

		
      	   PacketSize = process_8583(0, srBaseIsoFDT, obTranMapCurr.bitmap, unbuff, MSG_BUFF_SIZE-3);  //to pack
      	   memcpy(&SentBuff[2],&unbuff[5],PacketSize-5);
      	   
		   
			if (PacketSize>0) {
				SentBuff[0] = (PacketSize -5) / 256;
				SentBuff[1] = (PacketSize-5) % 256;
			}
      	   }
	  else
	  	{
	  	 	PacketSize = process_8583(0, srBaseIsoFDT, obTranMapCurr.bitmap, &SentBuff[2], MSG_BUFF_SIZE-3);  //to pack
			if (PacketSize>0) {
				SentBuff[0] = PacketSize / 256;
				SentBuff[1] = PacketSize % 256;
			}

	  	}
	LOG_PRINTFF((0x08L, "Packet Size = %d", PacketSize));
}
	return VS_SUCCESS;
	//return PacketSize;  //should return the PacketSize ==> NO NEED
			#else
	return VS_SUCCESS;
		#endif

}

int inImamUnpackAndValidateMessage(IMAM_TRANSACTION_OBJECT *pobTranEma, unsigned char *RecvBuff)
{
#ifndef IMAM_BNI
	int PacketSize;

	int i,inRetVal;
	char mode[3];

	char buff[128];
	long lnTmpTotal;
	int dbtpdu=0;
	int lenmsg;
	unsigned char RecvunBuff[MSG_BUFF_SIZE + 1];

	
    	
	unsigned char datame[8];
		memset(RecvunBuff,0x00,sizeof RecvunBuff);
	
	memset(datame,0x00,sizeof datame);
	memset(mode,0x00,sizeof mode);
	
	memset(buff, 0x00, sizeof(buff));
	inRetVal= get_env("DBTPDU", mode, sizeof(mode)-1);
	dbtpdu=atoi(mode);
	strcpy((char *)tpdu, (char *)szGetCPACTPDU()); //TPDU

   

   if (dbtpdu)
   	{
   	 
	  lenmsg = (int)((*(RecvBuff)<<8)& 0xff00);
	 lenmsg |= (int)*(RecvBuff+1);
    
	 memcpy(RecvunBuff,tpdu,5);
	 memcpy(&RecvunBuff[5],&RecvBuff[2],lenmsg);
	 memcpy(datame,&RecvunBuff[5],8);
	
       PacketSize = process_8583(1, srBaseIsoFDT,datame /*obTranMapCurr.bitmap*/, RecvunBuff, lenmsg+5);  //to unpack, isomap will be ignored
   	}
   else
   	{
   	  memcpy(datame,&RecvBuff[2+5],8);
    	PacketSize = process_8583(1, srBaseIsoFDT,datame /*obTranMapCurr.bitmap*/, &RecvBuff[2], (RecvBuff[0]*256 + RecvBuff[1]));  //to unpack, isomap will be ignored

   	}
////////////////////
//Checking Message Integrity
////////////////////
	LOG_PRINTFF((0x08L, "Unprocessed Recv Packet = %d %d", PacketSize,RecvBuff[0]*256 + RecvBuff[1]));
	if (PacketSize < 0) { //Kelebihan packet allowed
		DisplayStatus("Invalid Msg Response!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return VS_ERR;
	}


	memset(buff, 0x00, sizeof(buff));
	strcpy(buff, (char *)szGetCPACTID());
	if (strlen((char *)srISO.pszField41)) {
		if (strcmp(buff, (char *)srISO.pszField41)){
		  DisplayStatus("TID Check Failed!");
		  vdWarnBeep();
		  SVC_WAIT(2000);		
		  return VS_ERR;
		}
	} else {
		DisplayStatus("No TID Field!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return VS_ERR;
	}
/////////////////////
//Response Code Check
/////////////////////
	if (strlen((char *)srISO.pszField39)==2) {
		strcpy(pobTranEma->szRespCode, (char *)srISO.pszField39);
	} else {
		DisplayStatus("Approval Code Failed!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return VS_ERR;
	}

	if ((char)RecvBuff[2+7] & (char)0x10) { //Checking the existance of bit 4)
	   if (strlen((char *)srISO.pszField04)>=2) {
		  //pobTranEma->Total = strtol((char *)srISO.pszField04, NULL, 10);
		  memset(pobTranEma->szTotal, 0x00, sizeof(pobTranEma->szTotal));	
		  strcpy(pobTranEma->szTotal, (char *)srISO.pszField04);
		  srISO.pszField04[strlen((char *)srISO.pszField04)-2] = 0x00;
		  lnTmpTotal = atol((char *)srISO.pszField04);
		  LOG_PRINTFF((0x08L, "%s ==> %ld", (char *)srISO.pszField04, lnTmpTotal));
	   } else {
		  lnTmpTotal = 0;
	   }
	   pobTranEma->Total = lnTmpTotal;
	}

	if (strlen((char *)srISO.pszField12))
		strcpy(pobTranEma->szTime, (char *)srISO.pszField12);

	if (strlen((char *)srISO.pszField13))
		strcpy(&pobTranEma->szDate[2], (char *)srISO.pszField13);

	if (strlen((char *)srISO.pszField37))
		strcpy(pobTranEma->szRetRefNum, (char *)srISO.pszField37);

	if (strlen((char *)srISO.pszField38))
		strcpy(pobTranEma->szAuthCode, (char *)srISO.pszField38);
    if (pobTranEma->inCode==PMT_TRX_MINI_STATEMENT)
    	{
	if (32==(strlen((char *)srISO.pszField48))) 
		{
		iBniSetWKey3D((char *)srISO.pszField48);
		}
	else
		{
		 DisplayStatus("TPK Not Exist!");
		vdWarnBeep();
		SVC_WAIT(2000);		
		return VS_ERR;
		}
    	}

///////////////////
	//inDisplayHostResponse(pobTranEma);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int inDisplayHostResponse(IMAM_TRANSACTION_OBJECT *pobTranEma)
{
#ifndef IMAM_BNI
	char buff[42];
	char buff1[42];
	char buff2[42];

	memset(buff, 0x00, sizeof(buff));
	if (strlen((char *)srISO.pszField63)>40) 
		{ strncpy(buff, (char *)srISO.pszField63, 40);
	} 	else if (strlen((char *)srISO.pszField63)){
		strcpy(buff, (char *)srISO.pszField63);
	} 
	   else if (!strcmp(pobTranEma->szRespCode, "00")) {
		sprintf(buff, "Approved - %s", pobTranEma->szRespCode);
	} 
	   else if (!strcmp(pobTranEma->szRespCode, "02")) {
		sprintf(buff, "Declined - %s", pobTranEma->szRespCode);
	} 
	   else {
		sprintf(buff, "System Error - %s", pobTranEma->szRespCode);
	}

	if (strcmp(pobTranEma->szRespCode, "00")) 
		vdWarnBeep();
/// perubahannya 
if (pobTranEma->inCode ==PMT_TRX_MINI_STATEMENT)
{
	memset(buff1, 0x00, sizeof(buff1));
	memset(buff2, 0x00, sizeof(buff2));
	if (strlen(buff) > 20) {
		strncpy(buff1, buff, 20);
		strcpy(buff2, &buff[20]);
	} else {
		strcpy(buff1, buff);
	}
	vdTrimSpace(buff1);
	vdTrimSpace(buff2);
	LOG_PRINTFF((0x08L, "BIT63 = [%s]", buff));
	LOG_PRINTFF((0x08L, "Line1 = [%s]", buff1));
	LOG_PRINTFF((0x08L, "Line2 = [%s]", buff2));
	#if 1 //def IMAM_DBS
	vdFormatText(buff1, 21, CENTERED);
	DisplayStatus(buff1);
	if (strlen(buff2)){
		//if (pobTranEma->inCode==PMT_TRX_PURCHASE) 
		//	vdDisplayMerchantName();
		vdScrollDisplay();
		vdFormatText(buff2, 21, CENTERED);
		DisplayStatus(buff2);
	}
	#endif
}// end Perubahan 

	if (strcmp(pobTranEma->szRespCode, "00")) {
		//SVC_WAIT(3000);
		pause(6000);
		return VS_ERR;
	}
	SVC_WAIT(0);
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int	inImamDisplayResponse(IMAM_TRANSACTION_OBJECT *pobTranEma, unsigned long lnShowTime)
{

	char hrf[20];
	char buff[60];
	char buff2[60];
	char szCurr[5];
	
	if (strcmp(pobTranEma->szRespCode, "00") && strcmp(pobTranEma->szRespCode, "55")) return 0;

	memset(buff, 0x00, sizeof(buff));
	memset(hrf, 0x00, sizeof(hrf));
	get_font(hrf);
	set_font("");
	ClearSevenLine();
	
	inDisplayHostResponse(pobTranEma);
		vdScrollDisplay();
		vdScrollDisplay();
		vdScrollDisplay();
	pause(lnShowTime/10L);
	set_font(hrf);
	return VS_SUCCESS;
}




int inImamSendAndReceiveMessage(IMAM_TRANSACTION_OBJECT *pobTranEma, unsigned char *SentBuff, unsigned char *RecvBuff, int Reversal)
{
#ifndef IMAM_BNI
    int inRetVal = 0;                               
	unsigned char buff[MSG_BUFF_SIZE+1];
	int SentSize = SentBuff[0]*256 + SentBuff[1];
	int RecvSize = 0;
	int shUCLType = 0;
	int inTimeOut;

	//SVC_WAIT(3000);
    if (obCommunication.inCheck){
        if (obCommunication.inCheck(&obCommunication) != VS_SUCCESS){
            DisplayStatus("Not Connected!");
			return VS_ERR;
        }
    }
	memset(buff, 0x00, sizeof(buff));
	memcpy((char *)buff, (char *)SentBuff, SentSize+2);
	LOG_PRINTFF((0x08L, "inReqSiz is (%d-2)", SentSize+2));
	LOG_PRINT_HEX(buff, SentSize+2);

#ifdef IMAM_UCL
	shUCLType = inGetCurrentUCLCommLink();
#endif
#ifndef IMAM_DBS
	if ((fAES()) && (shUCLType != 0)) { // encrypt data
		unsigned long ticks;
		unsigned char szSendBuffTmp[1024];
		int inSendSizeTmp = SentSize+2;
		int iRet;
		memset(szSendBuffTmp, 0x00, sizeof(szSendBuffTmp));
		memcpy(szSendBuffTmp, (char *)SentBuff, inSendSizeTmp);
		memset(SentBuff, 0x00, sizeof(SentBuff));
		ticks = read_ticks();
		iRet = inImamAesEncrypt(szSendBuffTmp, inSendSizeTmp, SentBuff, &SentSize);
		memmove(&SentBuff[2], SentBuff, SentSize);
		SentBuff[0] = SentSize/256;
		SentBuff[1] = SentSize%256;
		//SendSize = SendSize + 2;
		LOG_PRINTFF((0x08L, "AES Encrypt Time Taken = [%ld ms]", read_ticks()-ticks));
		if (iRet != 0)
			return VS_ERR;  //encrypt err
	}
	#endif

    if (obCommunication.inSend) {
		BT_REQUEST_TRACE('B', &SentBuff[2], SentSize);
		#if 0
		if (inImamFindAndSendReversal()<=0) {
			DisplayStatus("Reversal Fail!");
			SVC_WAIT(2000);
			obCommunication.inEnd(&obCommunication);
			LOG_PRINTFF((0x08L, "Error in Process Reversal!!!"));
			return VS_ERR;
		}
		#endif
		if (shUCLType == 0 || shUCLType == 1 || shUCLType == 3 || shUCLType == 9)  {
			inRetVal = obCommunication.inSend(&obCommunication, (char *)&SentBuff[2], SentSize, VS_FALSE, SEND_COMM_TIMEOUT, TRANSMITTING_MSG21);
		} else {
			SentSize = SentSize + 2;
			inRetVal = obCommunication.inSend(&obCommunication, (char *)SentBuff, SentSize, VS_FALSE, SEND_COMM_TIMEOUT, TRANSMITTING_MSG21);            
		}
        if ((inRetVal == E_NOCARRIER) ||(inRetVal == E_X_NOCARRIER) || (inRetVal == VS_CARRIER)) {
			DisplayStatus("NO CARRIER");
			obCommunication.inEnd(&obCommunication);
			return VS_ERR;
        }
		#if 0
		if (Reversal) {
			inImamRestartFlag++;  //ONLY FINANCIAL TRX COUNT
			inImamSaveBatchRecordForReversal(pobTranEma);
		}
		#endif
		if (inRetVal != SentSize){
			DisplayStatus("Sending Message Fail!");        
			obCommunication.inEnd(&obCommunication);
			return VS_ERR;
		}
		{
			memset(buff, 0x00, sizeof(buff));
			memcpy((char *)buff, (char *)&SentBuff[2], SentSize);
			inImamPrintISOPacket(VS_TRUE, buff , SentSize);
		}
    }
	inTimeOut = 3000;
#ifdef MODEM
	if (inGetUCLCommLink()==0) {  // to get resp timeout
		MODEM_OBJECT *obModem;
		obModem = (MODEM_OBJECT *)obCommunication.Data;
		inTimeOut = obModem->shGetRespTimeOut(obModem->srCPT);  // for Response TimeOut
		inTimeOut = inTimeOut * 100;
		LOG_PRINTFF((0x08L, "GET TIMEOUT = [%d]", inTimeOut));
		//obModem->shGetCarrierTimeOut(obModem->srCPT); // for Carier TimeOut
	}
#endif
    if (obCommunication.inReceive) {
		if (shUCLType == 0 || shUCLType == 1 || shUCLType == 3 || shUCLType == 9)  {
			inRetVal = obCommunication.inReceive(&obCommunication, (char *)&RecvBuff[2], MSG_BUFF_SIZE-3, inTimeOut, PROCESSING_MSG21);
		} else {
			inRetVal = obCommunication.inReceive(&obCommunication, (char *)RecvBuff, MSG_BUFF_SIZE-3, inTimeOut, PROCESSING_MSG21);
		}
		if (inRetVal>0) RecvSize=inRetVal; //this line for UCL only
	}

	//SVC_WAIT(3000);
	LOG_PRINTFF((0x08L, "inRetVal is (%d)", inRetVal));
	LOG_PRINTFF((0x08L, "RecvSize is (%d)", RecvSize));
    if((inRetVal == E_NOCARRIER) ||(inRetVal == E_X_NOCARRIER) || (inRetVal == VS_CARRIER)) {
	//	inImamFindAndSendReversal();
		DisplayStatus("LOST CARRIER!");
		vdWarnBeep();
		SVC_WAIT(2000);
		return VS_ERR;
    } else if (inRetVal <= 0 || inRetVal != RecvSize) {
	//	inImamFindAndSendReversal();
		DisplayStatus("COM ERROR!");
		vdWarnBeep();
		SVC_WAIT(2000);
		return VS_ERR;
    } else {
		memset(buff, 0x00, sizeof(buff));
		memcpy((char *)buff, (char *)&RecvBuff[2], RecvSize);		
		inImamPrintISOPacket(VS_FALSE, buff , RecvSize);
		#if 0
		if (fAES() && (shUCLType != 0) && (inRetVal>10)) { // decrypt data
			unsigned char szRecvBuffTmp[1024];
			int inRecvSizeTmp = inRetVal-2;
			int iRet;
			memset(szRecvBuffTmp, 0x00, sizeof(szRecvBuffTmp));
			memcpy(szRecvBuffTmp, &RecvBuff[2], inRecvSizeTmp);
			memset(RecvBuff, 0x00, sizeof(RecvBuff));	
			iRet = inImamAesDecrypt(szRecvBuffTmp, inRecvSizeTmp, RecvBuff, &RecvSize);
			LOG_PRINTFF((0x08L, "[DECRYPTED (%d)]", RecvSize));
			LOG_PRINT_HEX((unsigned char *)RecvBuff, RecvSize);
			inRetVal = RecvSize;
			if (iRet != 0)
				return VS_ERR;  //decrypt err
		} 
		#endif
	
		if (shUCLType == 0 || shUCLType == 1 || shUCLType == 3 || shUCLType == 9)  { 
			RecvBuff[0] = (inRetVal) / 256;
			RecvBuff[1] = (inRetVal) % 256;
		} else {
			RecvBuff[0] = (inRetVal-2) / 256; //temporary for BCD type host
			RecvBuff[1] = (inRetVal-2) % 256;
		}
			memset(buff, 0x00, sizeof(buff));
		memcpy((char *)buff, (char *)RecvBuff, RecvSize);
		LOG_PRINTFF((0x08L,     "inTxRx8583, NoOfBytes = %d", inRetVal));
		LOG_PRINT_HEX(buff, RecvSize);
	}
	return VS_SUCCESS;
			#else
	return VS_SUCCESS;
		#endif

}


int inBeginComm(void)
{
#ifndef IMAM_BNI
    if (obCommunication.inBegin) {
        if (obCommunication.inBegin(&obCommunication, shGetCommunicationIndex(), VS_TRUE) != VS_SUCCESS){
			DisplayStatus("CONNECTION FAIL");
            return (VS_ERR);
        }
		return (VS_SUCCESS);
	}
	return (VS_ERR);
			#else
	return VS_SUCCESS;
		#endif

}

int inEndComm(void)
{
#ifndef IMAM_BNI
	if (obCommunication.inEnd) {
		obCommunication.inEnd(&obCommunication);
	}
	return (VS_SUCCESS);
			#else
	return VS_SUCCESS;
		#endif

}

void vdImamFreeVariantTables(void) 
{
#ifndef IMAM_BNI
    if (psrVariant60 == NULL){
		LOG_PRINTFF((0x08L, "psrVariant60==NULL"));
	} else {
		vdFree((char *) psrVariant60);
		psrVariant60 = NULL;
		LOG_PRINTFF((0x08L, "psrVariant60 FREE-ED"));
    } 

	if (psrVariant63 == NULL){
		LOG_PRINTFF((0x08L, "psrVariant63==NULL"));
	} else {
		vdFree((char *) psrVariant63);
		psrVariant63 = NULL;
		LOG_PRINTFF((0x08L, "psrVariant63 FREE-ED"));
	}
		#endif 
	return ;
}

int inImamCreateVariantTables(void) 
{
#ifndef IMAM_BNI
	memset(&srISO, 0x00, sizeof(ISO_DATA));

	if (inCPACCreateVariantStruct60() == VS_ERR) {
        //vdFree((char *) psrVariant60);
        //vdSGErrorMessage(NO_MEM_ERR_MSG);
        return(VS_ERR);
    }
    if (inCPACCreateVariantStruct63() == VS_ERR) {
        //vdFreeVariantTables();
        //vdSGErrorMessage(NO_MEM_ERR_MSG);
        return(VS_ERR);
    }
	//LOG_PRINTFF((0x08L, "AFTER CREATE psrVariant60 = %ld", (long)psrVariant60));
	//LOG_PRINTFF((0x08L, "AFTER CREATE psrVariant63 = %ld", (long)psrVariant63));
	return VS_SUCCESS;
		#else
	return VS_SUCCESS;
		#endif

}

int CreateBatchRecord(void)
{
#ifndef IMAM_BNI
	int fhandle;
	long countbyte;
	char buffer[128];
	IMAM_TRANSACTION_OBJECT pobTranEma;
	int i;

	memset((void *)&pobTranEma, 0x00, sizeof(IMAM_TRANSACTION_OBJECT));
	memset(buffer, 0x00, sizeof(buffer));
	if (get_env("#CZE" , buffer, sizeof(buffer)-1)>0) {
		if (buffer[0] == '1') {
			fhandle = open(IMAM_EMA_BATCH, O_CREAT|O_TRUNC|O_RDWR);
			if (fhandle != -1) {
				for (i=0; i<BATCH_SIZE; i++) {
					pobTranEma.RecordNo = 0;
					countbyte = write(fhandle, (const void *)&pobTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
					if (countbyte == sizeof(IMAM_TRANSACTION_OBJECT)) {
						sprintf(buffer, "Batch #%d x %ld", i+1, countbyte);
						DisplayStatus(buffer);
						//SVC_WAIT(100);
						//LOG_PRINTFF((0x08L,"%s", buffer));
					}else {
						sprintf(buffer, "Not Enough Memory!");
						write_at((const char *)buffer, strlen(buffer), 1, inImamLineNumber-1);
						LOG_PRINTFF((0x08L,"Not Enough Memory, MAX BATCH = %d", i));
						LOG_PRINTFF((0x08L,"Not Enough Memory, MAX BATCH = %d", i));
						LOG_PRINTFF((0x08L,"Not Enough Memory, MAX BATCH = %d", i));
						while(1);
					}
				}	
			}
			close(fhandle);
			//put_env("#CZE", "0", 1); //Softpay Init will make it 0
		}
	}
	DisplayStatus("STARTING...");
	return 1;
			#else
	return VS_SUCCESS;
		#endif

}


int ChooseBatchRecord(unsigned long lnInv, int Status, IMAM_TRANSACTION_OBJECT *pobTranEma)
{
#ifndef IMAM_BNI
	int karakter=0;  
	int fhandle;
	int i = 0;
	int line = 0;
	int found = 0;
	int bytes;
	int PrevRecordNo=0;
	int LastTrxRecNo = 0;
	char buff[100];
	char buff2[100];
	char TimeBuff[20];	
	memset(TimeBuff, 0x00, sizeof(TimeBuff));
	SVC_CLOCK(0, TimeBuff, 15);

	fhandle = open(IMAM_EMA_BATCH, O_RDWR);
	if (fhandle == -1) return VS_ERR;
	vdFlushKeyboardBuffer();
	do {
		memset((void *)pobTranEma, 0x00, sizeof(IMAM_TRANSACTION_OBJECT));
		bytes = read(fhandle, (void *)pobTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
		//if ((pobTranEma->STAN==inSTAN) && (pobTranEma->Status==Status || (Status==2 && pobTranEma->Status==3)) && (!strncmp(pobTranEma->szDate, &TimeBuff[2], 6))){
		if ((pobTranEma->lnInvNum==lnInv) && (pobTranEma->Status==Status || (Status==2 && pobTranEma->Status==3))){
			found = 1;
			break;
		}
	}while (bytes == sizeof(IMAM_TRANSACTION_OBJECT));

	if (!found) {
		display_at(1, inImamLineNumber-1, " ", CLR_EOL);
		write_at("Invalid Trace#!", 15, 1, 3);
		write_at("Continue ?", 10, 1, inImamLineNumber/2);
		if (inImamLineNumber == 16){
			write_at(" Yes"			, 4, 22-4, 10);
			write_at("  No"			, 4, 22-4, 13);
		} else {
			write_at(" Yes"			, 4, 22-4, 6);
			write_at("  No"			, 4, 22-4, 8);
		}
		set_font("F:asc8x21.vft");
		for(i=2; i<=inImamLineNumber; i++) write_at("|", 1, 22-5, i);
		set_font("");
		TimeOut(15000);
		do {
			if (KBHIT()) {
				karakter = get_char();
				TimeOut(15000);
			} else {
				if (TimeOut(0)) {
					close(fhandle);
					return VS_ERR;
				}
				SVC_WAIT(0);
				if (lnInv) {
					continue;
				} else {
					ClearSevenLine();
					write_at("Last Transaction...", 19, 1, inImamLineNumber-1);
					karakter=0x03;
				}
			}
			if (karakter == 0x0D || karakter == 0x03) { //enter or F3
				lseek(fhandle, (long)0, SEEK_SET);
				do {
					memset((void *)pobTranEma, 0x00, sizeof(IMAM_TRANSACTION_OBJECT));
					bytes = read(fhandle, (void *)pobTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
					if (bytes == sizeof(IMAM_TRANSACTION_OBJECT)){
						if (PrevRecordNo==0 || pobTranEma->RecordNo == PrevRecordNo+1) {
							PrevRecordNo = pobTranEma->RecordNo;
						} else {
							break;
						}
						if (pobTranEma->Status == Status) LastTrxRecNo = pobTranEma->RecordNo; 
						if (Status==2 && pobTranEma->Status==3) LastTrxRecNo = pobTranEma->RecordNo;
					}else{
						break;
					}
				}while (1);
				PrevRecordNo = LastTrxRecNo;
				if (PrevRecordNo == 0) {
					lseek(fhandle, (long)0, SEEK_SET);
				} else if (PrevRecordNo % BATCH_SIZE){
					lseek(fhandle, (long)(((PrevRecordNo % BATCH_SIZE)-1)*sizeof(IMAM_TRANSACTION_OBJECT)), SEEK_SET);
				} else {
					lseek(fhandle, (long)((BATCH_SIZE-1)*sizeof(IMAM_TRANSACTION_OBJECT)), SEEK_SET);
				}
				read(fhandle, (void *)pobTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
				if (LastTrxRecNo==0) {
					close(fhandle);
					DisplayStatus("No Batch Trxn!");
					SVC_WAIT(2000);
					return VS_ERR;
				}
				break;
			} else if (karakter == 0x1B || karakter == 0x04) { //esc or F4
				close(fhandle);
				return VS_ERR;
			} 
		} while(1);
	}

	do {
		ClearSevenLine();
		if (inImamLineNumber==16) {
			write_at(" Yes"			, 4, 22-4, 7);
			write_at("  No"			, 4, 22-4, 10);
			write_at("Next"			, 4, 22-4, 13);
			line=4;
		} else {
			write_at(" Yes"			, 4, 22-4, 4);
			write_at("  No"			, 4, 22-4, 6);
			write_at("Next"			, 4, 22-4, 8);
			line=2;
		}
		set_font("F:asc8x21.vft");
		for(i=2; i<=inImamLineNumber; i++) write_at("|", 1, 22-5, i);
		set_font("");

		memset(buff, 0x00, sizeof(buff));
		write_at(pobTranEma->szPAN, strlen(pobTranEma->szPAN), 1, line++);
		strcpy(buff, pobTranEma->szCHolder); buff[16] = 0x00;
		if (strlen(buff)) write_at(buff, strlen(buff), 1, line++);

		memset(buff, 0x00, sizeof(buff));
		vdImamGetEmaData(pobTranEma->TrxMenu.inDataID, 2, &buff[5]);
		if (pobTranEma->Status==4){
			strncpy(buff, "Void ", 5);
		} else {
			strcpy(buff, &buff[5]);
		}
		buff[16] = 0x00;
		write_at(buff, strlen(buff), 1, line++);
		//sprintf(buff, "Tr/Rec:%03d/%03d", pobTranEma->STAN, pobTranEma->RecordNo);
		sprintf(buff, "Trc: %06ld", pobTranEma->lnInvNum);
		write_at(buff, strlen(buff), 1, line++);
/*
		if (strlen(pobTranEma->szRcptAcc)) {
			sprintf(buff, "To :%s", pobTranEma->szRcptName);
			buff[16] = 0x00;
			write_at(buff, strlen(buff), 1, line++);
		}
*/
		if (pobTranEma->Point>0) {
			sprintf(buff, "Pax:%02ld", pobTranEma->Point);
			write_at(buff, strlen(buff), 1, line++);
		}
		if (pobTranEma->Total>0) {	
			memset(buff, 0x00, sizeof(buff));
			FormatNumInd(buff, pobTranEma->Total);
			write_at("RP : ", 5, 1, line);
			write_at(buff, strlen(buff), 6, line++);
		}

		TimeOut(15000);
		do { 
			if (KBHIT()) {
				karakter = get_char();
				break;
			}
			SVC_WAIT(0);
			if (TimeOut(0)) {
				close(fhandle);
				return VS_ERR;
			}
		}while(1);
		
		if (karakter == 0x0D || karakter == 0x02) { //enter or F2
			close(fhandle);
			return VS_SUCCESS;
		} else if (karakter == 0x1B || karakter == 0x03) { //esc or F3
			close(fhandle);
			return VS_ERR;
		} else if (karakter == 0x04){ //F4
			for (i=0; i<BATCH_SIZE; i++) {
				memset((void *)pobTranEma, 0x00, sizeof(IMAM_TRANSACTION_OBJECT));
				bytes = read(fhandle, (void *)pobTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
				if (bytes != sizeof(IMAM_TRANSACTION_OBJECT)) {
					lseek(fhandle, (long)0, SEEK_SET);
					read(fhandle, (void *)pobTranEma, sizeof(IMAM_TRANSACTION_OBJECT));
				}
				if (pobTranEma->Status==Status) 
					break;
				if (Status==2 && pobTranEma->Status==3) 
					break;
			}
		} 
	} while (1);
	close(fhandle);
	return VS_SUCCESS;
			#else
	return VS_SUCCESS;
		#endif

}


int inDisclaimer(char *szDisclaimer)
{
#ifndef IMAM_BNI
	char buff[22];
	int i, Mark, CurPos=0;
	int line=2;
    int ret=VS_ERR;
	if (inImamLineNumber == 16) line = 2 + 4;

	ClearSevenLine();
	for (i=CurPos; ; i++) {
		if ((szDisclaimer[i]==0x00) && (i-CurPos<22)) {
			memset(buff, 0x00, sizeof(buff));
			strcpy(buff, &szDisclaimer[CurPos]);
			write_at(buff, strlen(buff), (23-strlen(buff))/2, line++);
			break;
		}
		if ((szDisclaimer[i]==' ') && (i-CurPos<22)) {
			Mark = i;
		}
		if ((szDisclaimer[i]==' ' || szDisclaimer[i]==0x00) && (i-CurPos>=22)) {
			memset(buff, 0x00, sizeof(buff));
			if (Mark==0 || (i-Mark>=22)) Mark=CurPos+21;
			strncpy(buff, &szDisclaimer[CurPos], Mark-CurPos);
			if (szDisclaimer[Mark] == ' ') {CurPos = Mark+1;} else {CurPos = Mark;}
			i = Mark-1;
			write_at(buff, strlen(buff), (23-strlen(buff))/2, line++);
		}
	}
	if (inHorizontalMenuChoice("", "SETUJU", "", "", "BATAL")==1) {
		//return VS_SUCCESS;
		ret=VS_SUCCESS;
	} else {
		//return VS_ERR;
		ret= VS_ERR;
	}
//	return VS_ERR;

  return ret;
		#else
	return VS_SUCCESS;
		#endif

}

